package com.marketing.tenant.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.marketing.tenant.entity.SubscriptionPlan;
import com.marketing.tenant.entity.TenantSubscription;
import com.marketing.tenant.mapper.TenantSubscriptionMapper;
import com.marketing.tenant.service.SubscriptionPlanService;
import com.marketing.tenant.service.TenantSubscriptionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 租户订阅服务实现
 * 
 * @author Marketing System
 * @since 2024-09-25
 */
@Service
public class TenantSubscriptionServiceImpl implements TenantSubscriptionService {
    
    private static final Logger log = LoggerFactory.getLogger(TenantSubscriptionServiceImpl.class);
    
    @Autowired
    private TenantSubscriptionMapper subscriptionMapper;
    
    @Autowired
    private SubscriptionPlanService planService;
    
    @Override
    @Transactional
    public boolean createSubscription(TenantSubscription subscription) {
        try {
            subscription.setCreateTime(LocalDateTime.now());
            subscription.setUpdateTime(LocalDateTime.now());
            
            int result = subscriptionMapper.insert(subscription);
            log.info("创建订阅成功，租户ID: {}, 计划ID: {}", subscription.getTenantId(), subscription.getPlanId());
            return result > 0;
        } catch (Exception e) {
            log.error("创建订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("创建订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public TenantSubscription subscribePlan(Long tenantId, Long planId, Integer months) {
        try {
            // 检查订阅计划是否存在且可用
            SubscriptionPlan plan = planService.getPlanById(planId);
            if (plan == null || plan.getStatus() != 1) {
                throw new RuntimeException("订阅计划不存在或不可用，计划ID: " + planId);
            }
            
            // 检查租户是否已有活跃订阅
            TenantSubscription currentSubscription = getCurrentSubscription(tenantId);
            if (currentSubscription != null) {
                throw new RuntimeException("租户已有活跃订阅，请先取消当前订阅");
            }
            
            // 创建新订阅
            TenantSubscription subscription = new TenantSubscription();
            subscription.setTenantId(tenantId);
            subscription.setPlanId(planId);
            subscription.setStatus("ACTIVE");
            subscription.setStartDate(LocalDate.now());
            subscription.setEndDate(LocalDate.now().plusMonths(months));
            subscription.setAutoRenew(1);
            subscription.setPaymentStatus("PAID");
            
            // 计算价格
            java.math.BigDecimal totalPrice = plan.getPrice().multiply(java.math.BigDecimal.valueOf(months));
            subscription.setTotalAmount(totalPrice);
            
            createSubscription(subscription);
            
            // 设置关联的计划信息
            subscription.setPlan(plan);
            
            log.info("租户订阅成功，租户ID: {}, 计划: {}, 订阅月数: {}", tenantId, plan.getPlanName(), months);
            return subscription;
        } catch (Exception e) {
            log.error("租户订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean renewSubscription(Long tenantId, Integer months) {
        try {
            TenantSubscription currentSubscription = getCurrentSubscription(tenantId);
            if (currentSubscription == null) {
                throw new RuntimeException("租户没有有效订阅，租户ID: " + tenantId);
            }
            
            // 延长订阅时间
            LocalDate newEndDate = currentSubscription.getEndDate().plusMonths(months);
            currentSubscription.setEndDate(newEndDate);
            currentSubscription.setUpdateTime(LocalDateTime.now());
            
            // 计算续费价格
            SubscriptionPlan plan = planService.getPlanById(currentSubscription.getPlanId());
            if (plan != null) {
                java.math.BigDecimal renewPrice = plan.getPrice().multiply(java.math.BigDecimal.valueOf(months));
                currentSubscription.setTotalAmount(currentSubscription.getTotalAmount().add(renewPrice));
            }
            
            int result = subscriptionMapper.updateById(currentSubscription);
            log.info("续费成功，租户ID: {}, 续费月数: {}, 新到期时间: {}", tenantId, months, newEndDate);
            return result > 0;
        } catch (Exception e) {
            log.error("续费失败: {}", e.getMessage(), e);
            throw new RuntimeException("续费失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean upgradeSubscription(Long tenantId, Long newPlanId) {
        try {
            TenantSubscription currentSubscription = getCurrentSubscription(tenantId);
            if (currentSubscription == null) {
                throw new RuntimeException("租户没有有效订阅，租户ID: " + tenantId);
            }
            
            SubscriptionPlan newPlan = planService.getPlanById(newPlanId);
            if (newPlan == null || newPlan.getStatus() != 1) {
                throw new RuntimeException("新订阅计划不存在或不可用，计划ID: " + newPlanId);
            }
            
            SubscriptionPlan currentPlan = planService.getPlanById(currentSubscription.getPlanId());
            if (currentPlan != null && newPlan.getPrice().compareTo(currentPlan.getPrice()) <= 0) {
                throw new RuntimeException("新计划价格必须高于当前计划才能升级");
            }
            
            // 更新订阅计划
            currentSubscription.setPlanId(newPlanId);
            currentSubscription.setUpdateTime(LocalDateTime.now());
            
            int result = subscriptionMapper.updateById(currentSubscription);
            log.info("升级订阅成功，租户ID: {}, 新计划: {}", tenantId, newPlan.getPlanName());
            return result > 0;
        } catch (Exception e) {
            log.error("升级订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("升级订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean downgradeSubscription(Long tenantId, Long newPlanId) {
        try {
            TenantSubscription currentSubscription = getCurrentSubscription(tenantId);
            if (currentSubscription == null) {
                throw new RuntimeException("租户没有有效订阅，租户ID: " + tenantId);
            }
            
            SubscriptionPlan newPlan = planService.getPlanById(newPlanId);
            if (newPlan == null || newPlan.getStatus() != 1) {
                throw new RuntimeException("新订阅计划不存在或不可用，计划ID: " + newPlanId);
            }
            
            SubscriptionPlan currentPlan = planService.getPlanById(currentSubscription.getPlanId());
            if (currentPlan != null && newPlan.getPrice().compareTo(currentPlan.getPrice()) >= 0) {
                throw new RuntimeException("新计划价格必须低于当前计划才能降级");
            }
            
            // 更新订阅计划（降级通常在下一个计费周期生效）
            currentSubscription.setPlanId(newPlanId);
            currentSubscription.setUpdateTime(LocalDateTime.now());
            
            int result = subscriptionMapper.updateById(currentSubscription);
            log.info("降级订阅成功，租户ID: {}, 新计划: {}", tenantId, newPlan.getPlanName());
            return result > 0;
        } catch (Exception e) {
            log.error("降级订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("降级订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean cancelSubscription(Long tenantId) {
        try {
            TenantSubscription currentSubscription = getCurrentSubscription(tenantId);
            if (currentSubscription == null) {
                throw new RuntimeException("租户没有有效订阅，租户ID: " + tenantId);
            }
            
            currentSubscription.setStatus("CANCELLED");
            currentSubscription.setAutoRenew(0);
            currentSubscription.setUpdateTime(LocalDateTime.now());
            
            int result = subscriptionMapper.updateById(currentSubscription);
            log.info("取消订阅成功，租户ID: {}", tenantId);
            return result > 0;
        } catch (Exception e) {
            log.error("取消订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("取消订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean pauseSubscription(Long tenantId) {
        try {
            TenantSubscription currentSubscription = getCurrentSubscription(tenantId);
            if (currentSubscription == null) {
                throw new RuntimeException("租户没有有效订阅，租户ID: " + tenantId);
            }
            
            currentSubscription.setStatus("SUSPENDED");
            currentSubscription.setUpdateTime(LocalDateTime.now());
            
            int result = subscriptionMapper.updateById(currentSubscription);
            log.info("暂停订阅成功，租户ID: {}", tenantId);
            return result > 0;
        } catch (Exception e) {
            log.error("暂停订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("暂停订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean resumeSubscription(Long tenantId) {
        try {
            LambdaQueryWrapper<TenantSubscription> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantSubscription::getTenantId, tenantId)
                   .eq(TenantSubscription::getStatus, "SUSPENDED")
                   .orderByDesc(TenantSubscription::getCreateTime)
                   .last("LIMIT 1");
            
            TenantSubscription subscription = subscriptionMapper.selectOne(wrapper);
            if (subscription == null) {
                throw new RuntimeException("租户没有暂停的订阅，租户ID: " + tenantId);
            }
            
            subscription.setStatus("ACTIVE");
            subscription.setUpdateTime(LocalDateTime.now());
            
            int result = subscriptionMapper.updateById(subscription);
            log.info("恢复订阅成功，租户ID: {}", tenantId);
            return result > 0;
        } catch (Exception e) {
            log.error("恢复订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("恢复订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    public TenantSubscription getCurrentSubscription(Long tenantId) {
        try {
            LambdaQueryWrapper<TenantSubscription> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantSubscription::getTenantId, tenantId)
                   .eq(TenantSubscription::getStatus, "ACTIVE")
                   .ge(TenantSubscription::getEndDate, LocalDate.now())
                   .orderByDesc(TenantSubscription::getEndDate)
                   .last("LIMIT 1");
            
            TenantSubscription subscription = subscriptionMapper.selectOne(wrapper);
            if (subscription != null && subscription.getPlanId() != null) {
                // 加载关联的计划信息
                SubscriptionPlan plan = planService.getPlanById(subscription.getPlanId());
                subscription.setPlan(plan);
            }
            return subscription;
        } catch (Exception e) {
            log.error("查询当前订阅失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public IPage<TenantSubscription> getSubscriptionHistory(Page<TenantSubscription> page, Long tenantId) {
        try {
            LambdaQueryWrapper<TenantSubscription> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantSubscription::getTenantId, tenantId)
                   .orderByDesc(TenantSubscription::getCreateTime);
            
            IPage<TenantSubscription> result = subscriptionMapper.selectPage(page, wrapper);
            
            // 加载关联的计划信息
            result.getRecords().forEach(subscription -> {
                if (subscription.getPlanId() != null) {
                    SubscriptionPlan plan = planService.getPlanById(subscription.getPlanId());
                    subscription.setPlan(plan);
                }
            });
            
            return result;
        } catch (Exception e) {
            log.error("查询订阅历史失败: {}", e.getMessage(), e);
            throw new RuntimeException("查询订阅历史失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<TenantSubscription> getExpiringSubscriptions() {
        try {
            LocalDate expiringDate = LocalDate.now().plusDays(7);
            LambdaQueryWrapper<TenantSubscription> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantSubscription::getStatus, "ACTIVE")
                   .between(TenantSubscription::getEndDate, LocalDate.now(), expiringDate);
            return subscriptionMapper.selectList(wrapper);
        } catch (Exception e) {
            log.error("查询即将到期订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("查询即将到期订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<TenantSubscription> getExpiredSubscriptions() {
        try {
            LambdaQueryWrapper<TenantSubscription> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantSubscription::getStatus, "ACTIVE")
                   .lt(TenantSubscription::getEndDate, LocalDate.now());
            return subscriptionMapper.selectList(wrapper);
        } catch (Exception e) {
            log.error("查询已过期订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("查询已过期订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public int processExpiredSubscriptions() {
        try {
            LambdaQueryWrapper<TenantSubscription> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TenantSubscription::getStatus, "ACTIVE")
                   .lt(TenantSubscription::getEndDate, LocalDate.now());
            
            List<TenantSubscription> expiredSubscriptions = subscriptionMapper.selectList(wrapper);
            int count = 0;
            
            for (TenantSubscription subscription : expiredSubscriptions) {
                subscription.setStatus("EXPIRED");
                subscription.setUpdateTime(LocalDateTime.now());
                subscriptionMapper.updateById(subscription);
                count++;
            }
            
            log.info("处理过期订阅完成，处理数量: {}", count);
            return count;
        } catch (Exception e) {
            log.error("处理过期订阅失败: {}", e.getMessage(), e);
            throw new RuntimeException("处理过期订阅失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean hasActiveSubscription(Long tenantId) {
        try {
            TenantSubscription subscription = getCurrentSubscription(tenantId);
            return subscription != null && "ACTIVE".equals(subscription.getStatus());
        } catch (Exception e) {
            log.error("检查有效订阅失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public boolean hasFeatureAccess(Long tenantId, String feature) {
        try {
            TenantSubscription subscription = getCurrentSubscription(tenantId);
            if (subscription == null || !"ACTIVE".equals(subscription.getStatus())) {
                return false;
            }
            
            SubscriptionPlan plan = subscription.getPlan();
            if (plan == null) {
                plan = planService.getPlanById(subscription.getPlanId());
            }
            
            if (plan != null && plan.getFeatures() != null) {
                return plan.getFeatures().contains(feature);
            }
            
            return false;
        } catch (Exception e) {
            log.error("检查功能权限失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public Integer getUsageLimit(Long tenantId, String limitType) {
        try {
            TenantSubscription subscription = getCurrentSubscription(tenantId);
            if (subscription == null || !"ACTIVE".equals(subscription.getStatus())) {
                return 0;
            }
            
            SubscriptionPlan plan = subscription.getPlan();
            if (plan == null) {
                plan = planService.getPlanById(subscription.getPlanId());
            }
            
            // 这里需要根据实际的限制配置来实现
            if ("max_users".equals(limitType)) {
                return plan.getMaxUsers();
            } else if ("max_storage".equals(limitType)) {
                return plan.getMaxStorage().intValue();
            }
            
            return 0;
        } catch (Exception e) {
            log.error("获取使用限制失败: {}", e.getMessage(), e);
            return 0;
        }
    }
    
    @Override
    public Object getSubscriptionStats(Long planId, LocalDateTime startDate, LocalDateTime endDate) {
        try {
            Map<String, Object> stats = new HashMap<>();
            
            // 构建查询条件
            LambdaQueryWrapper<TenantSubscription> wrapper = new LambdaQueryWrapper<>();
            wrapper.between(TenantSubscription::getCreateTime, startDate, endDate);
            if (planId != null) {
                wrapper.eq(TenantSubscription::getPlanId, planId);
            }
            
            // 统计总订阅数
            Long totalSubscriptions = subscriptionMapper.selectCount(wrapper);
            stats.put("totalSubscriptions", totalSubscriptions);
            
            // 统计活跃订阅数
            wrapper.eq(TenantSubscription::getStatus, "ACTIVE");
            Long activeSubscriptions = subscriptionMapper.selectCount(wrapper);
            stats.put("activeSubscriptions", activeSubscriptions);
            
            // 统计取消订阅数
            wrapper.clear();
            wrapper.between(TenantSubscription::getCreateTime, startDate, endDate)
                   .eq(TenantSubscription::getStatus, "CANCELLED");
            if (planId != null) {
                wrapper.eq(TenantSubscription::getPlanId, planId);
            }
            Long cancelledSubscriptions = subscriptionMapper.selectCount(wrapper);
            stats.put("cancelledSubscriptions", cancelledSubscriptions);
            
            // 计算订阅率
            if (totalSubscriptions > 0) {
                double retentionRate = (double) (totalSubscriptions - cancelledSubscriptions) / totalSubscriptions * 100;
                stats.put("retentionRate", Math.round(retentionRate * 100.0) / 100.0);
            } else {
                stats.put("retentionRate", 0.0);
            }
            
            return stats;
        } catch (Exception e) {
            log.error("获取订阅统计失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取订阅统计失败: " + e.getMessage());
        }
    }
}